package cn.lili.modules.store.serviceimpl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.lili.cache.Cache;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.utils.BeanUtil;
import cn.lili.common.utils.GISUtil;
import cn.lili.common.vo.PageVO;
import cn.lili.modules.store.entity.dos.StoreInfo;
import cn.lili.modules.store.entity.dto.StoreInfoEditDTO;
import cn.lili.modules.store.entity.dto.StoreInfoListDTO;
import cn.lili.modules.store.entity.vos.StoreInfoSearchParams;
import cn.lili.modules.store.entity.vos.StoreInfoVO;
import cn.lili.modules.store.mapper.StoreInfoMapper;
import cn.lili.modules.store.service.StoreInfoService;
import cn.lili.mybatis.util.PageUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 店铺业务层实现
 *
 * @author pikachu
 * @since 2020-03-07 16:18:56
 */
@Service
public class StoreInfoServiceImpl extends ServiceImpl <StoreInfoMapper, StoreInfo> implements StoreInfoService {

    @Autowired
    private Cache cache;

    @Override
    public IPage <StoreInfoVO> findByConditionPage(StoreInfoSearchParams storeInfoSearchParams, PageVO page) {
        return this.baseMapper.getStoreInfoList(PageUtil.initPage(page), storeInfoSearchParams.queryWrapper());
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public StoreInfo add(StoreInfoEditDTO storeInfoEditDTO) {

        if (storeInfoEditDTO != null) {
            //判断门店名是否唯一
            QueryWrapper<StoreInfo> queryWrapper = Wrappers.query();
            queryWrapper.eq("store_name", storeInfoEditDTO.getStoreName());
            if (this.getOne(queryWrapper) != null) {
                throw new ServiceException(ResultCode.STORE_INFO_NAME_EXIST_ERROR);
            }

            StoreInfo storeInfo = new StoreInfo();
            BeanUtil.copyProperties(storeInfoEditDTO, storeInfo);
            this.save(storeInfo);
            return storeInfo;
        } else {
            throw new ServiceException(ResultCode.PARAMS_ERROR);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StoreInfo edit(StoreInfoEditDTO storeInfoEditDTO) {
        if (storeInfoEditDTO != null) {
            //判断店铺名是否唯一
            StoreInfo storeTmp = getOne(new QueryWrapper <StoreInfo>().eq("store_name", storeInfoEditDTO.getStoreName()));
            if (storeTmp != null && !CharSequenceUtil.equals(storeTmp.getId(), storeInfoEditDTO.getId())) {
                throw new ServiceException(ResultCode.STORE_INFO_NAME_EXIST_ERROR);
            }

            StoreInfo storeInfo = this.getById(storeInfoEditDTO.getId());
            if (storeInfo != null) {
                BeanUtil.copyProperties(storeInfoEditDTO, storeInfo);
                boolean result = this.updateById(storeInfo);
                return storeInfo;
            } else {
                throw new ServiceException(ResultCode.STORE_INFO_NOT_EXIST);
            }
        } else {
            throw new ServiceException(ResultCode.STORE_INFO_NOT_EXIST);
        }
    }

    @Override
    public List <StoreInfoVO> getByLocation(StoreInfoListDTO dto) {
        List <StoreInfo> storeInfos = this.lambdaQuery().ge(StoreInfo::getDeleteFlag, 0).list();
        List <StoreInfoVO> storeInfoVOS = JSON.parseArray(JSON.toJSONString(storeInfos), StoreInfoVO.class);
        //如果传了坐标，就把最近的放第一位
        Double longitude = dto.getLongitude();
        Double latitude = dto.getLatitude();
        if (ObjectUtil.isNotEmpty(dto.getLatitude()) && ObjectUtil.isNotEmpty(longitude) && CollUtil.isNotEmpty(storeInfoVOS)){

            storeInfoVOS.forEach(storeInfo -> {
                storeInfo.setDistance(GISUtil.GetDistance(Convert.toDouble(storeInfo.getLatitude()), Convert.toDouble(storeInfo.getLongitude()), latitude, longitude));
            });

            storeInfoVOS = storeInfoVOS.stream().sorted(Comparator.comparing(StoreInfoVO::getDistance)).collect(Collectors.toList());
        }


        return storeInfoVOS;
    }


}